package com.cooper.mediadb.online;

import java.util.HashMap;
import android.content.Context;
import android.util.Log;

import com.cooper.scraper.DownloadException;
import com.cooper.scraper.HttpDownload;
import com.cooper.scraper.ResourceCollector;
import com.cooper.scraper.ResourceScraper;
import com.cooper.scraper.ResourceScraperRunner;
import com.cooper.scraper.ResultUrl;
import com.cooper.scraper.ScraperException;
import com.cooper.scraper.ScraperManager;
import com.cooper.scraper.ScraperRunnerThread;
import com.cooper.scraper.ThreadPoolDownloadPublishRunner;

public final class OnlineMediaScrapeRunner extends
		ThreadPoolDownloadPublishRunner implements
		ResourceScraperRunner<OnlineMedia> {

	private static OnlineMediaScrapeRunner instance = null;

	public static OnlineMediaScrapeRunner getInstance() {
		if (instance == null) {
			instance = new OnlineMediaScrapeRunner();
		}
		return instance;
	}

	public static void destroyInstance() {
		if (instance != null) {
			instance.destroy();
			instance = null;
		}
	}

	private OnlineMediaScrapeRunner() {
		super();
	}

	@Override
	public void getBrowseParams(Context context, String scraperId) {
		run(ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX + scraperId,
				new DownloadBrowseParams(resultPool, context, scraperId));
	}

	class DownloadBrowseParams extends ScraperRunnerThread {

		private Context context;

		public DownloadBrowseParams(ResultPool resultPool, Context context,
				String scraperId) {
			super(resultPool, ResourceScraper.BROWSE_URL_PARAM_SUBSCRIBE_PREFIX
					+ scraperId, scraperId);
			this.context = context;
		}

		@Override
		protected Object runScraper() throws DownloadException,
				ScraperException {
			ResourceScraper<OnlineMedia> scraper = getOnlineMediaScraper(
					context, scraperId);
			return scraper.getBrowseUrlParams();
		}

	}

	@Override
	public void listResource(Context context,
			ResourceCollector<OnlineMedia> resultMedia) {
		String key = resultMedia.generateKey();
		if (resultMedia.ready()) {
			run(key, new DownloadResultMedia(resultPool, key, resultMedia));
		} else {
			run(key, new RunDownloadResultMedia(resultPool, context, key,
					resultMedia));
		}
	}

	class RunDownloadResultMedia extends RunnerThread {

		private ResourceCollector<OnlineMedia> resultMedias;
		private Context context;
		private boolean retry = false;
		private String key;

		public RunDownloadResultMedia(ResultPool resultPool, Context context,
				String key, ResourceCollector<OnlineMedia> resultMedias) {
			super(resultPool);
			this.key = key;
			this.context = context;
			this.resultMedias = resultMedias;
		}

		@Override
		public void run() {
			super.run();
			if (!resultMedias.ready()) {
				try {
					OnlineMediaScraper scraper = getOnlineMediaScraper(context,
							resultMedias.getScraperId());
					resultMedias.setScraper(scraper,
							scraper.getBrowseUrlParams());
					String downloadKey = resultMedias.generateKey();
					OnlineMediaScrapeRunner.this.run(downloadKey,
							new DownloadResultMedia(resultPool, downloadKey,
									resultMedias));
				} catch (ScraperException e) {
					if (!retry) {
						retry = true;
						ScraperManager.getInstance().cleanLocalScraper(
								resultMedias.getScraperId());
						resultMedias.setScraper(null, null);
						run();
					} else
						fail(key, e.getErrorCode());
				} catch (Exception e) {
					fail(key, DownloadException.ERROR_OTHER);
				}

			}

		}
	}

	static class DownloadResultMedia extends RunnerThread {

		private ResourceCollector<OnlineMedia> resultMedias;
		private String key;

		public DownloadResultMedia(ResultPool resultPool, String key,
				ResourceCollector<OnlineMedia> resultMedias) {
			super(resultPool);
			this.key = key;
			this.resultMedias = resultMedias;
		}

		@Override
		public void run() {
			super.run();
			try {
				if (!resultMedias.ready()) {
					return;
				}

				ResultUrl resultUrl = resultMedias.scraperListUrl();

				ResultUrl pageCountUrl = resultMedias.scraperPageCountUrl();

				boolean samePageCountPage = (pageCountUrl == null)
						|| pageCountUrl.equals(resultUrl);

				String redirectUrl = HttpDownload.getInstance().getRedirectUrl(
						resultUrl.getUrl());

				boolean redirect = false;
				if (!redirectUrl.equals(resultUrl.getUrl())) {
					resultUrl.setUrl(redirectUrl);
					redirect = true;
				}

				String page = HttpDownload.getInstance().downloadPage(
						resultUrl.getUrl(), resultUrl.getEncodingType(), false);
				if (!Thread.currentThread().isInterrupted()) {
					if (redirect) {
						resultMedias.scraperResult(page, resultUrl.getUrl(),
								redirectUrl);
					} else
						resultMedias.scraperResult(page, resultUrl.getUrl());

			
					if (!samePageCountPage) {
						redirect = false;
						redirectUrl = HttpDownload.getInstance()
								.getRedirectUrl(pageCountUrl.getUrl());

						if (!redirectUrl.equals(pageCountUrl.getUrl())) {
							pageCountUrl.setUrl(redirectUrl);
							redirect = true;
						}
						page = HttpDownload.getInstance().downloadPage(
								pageCountUrl.getUrl(),
								pageCountUrl.getEncodingType());
					}
					
					if (redirect) {
						Log.d("OnlineMediaScrapeRunner","prepare pageCount 1");
						resultMedias.scraperPageCount(page);
					} else {
						Log.d("OnlineMediaScrapeRunner","prepare pageCount 2");
						resultMedias.scraperPageCount(page, redirectUrl);
					}

				}
				Log.d("OnlineMediaScrapeRunner","scrape complete key:" +key);
				complete(key, resultMedias);
			} catch (DownloadException e) {
				fail(key, e.getErrorCode());
			} catch (ScraperException e) {
				ScraperManager.getInstance().cleanLocalScraper(
						resultMedias.getScraperId());
				fail(key, e.getErrorCode());
			} catch (Exception e) {
				Log.e("DownloadResultMovies.run", "result:" + resultMedias
						+ "resultUrl:", e);
				fail(key, DownloadException.ERROR_OTHER);
			}

		}
	}

	public void getResourceDetails(Context context, String scraperId,
			OnlineMedia media) {
		run(media.generateSubscribedKey(), new DownloadMediaDetails(resultPool,
				context, scraperId, media));
	}

	class DownloadMediaDetails extends ScraperRunnerThread {

		private OnlineMedia movie;

		// private ResourceScraper<OnlineMedia> scraper;
		private Context context;

		public DownloadMediaDetails(ResultPool resultPool, Context context,
				String scraperId, OnlineMedia movie) {
			super(resultPool, movie.generateSubscribedKey(), scraperId);
			this.movie = movie;
			this.context = context;
		}

		@Override
		protected Object runScraper() throws DownloadException,
				ScraperException {
			ResourceScraper<OnlineMedia> scraper = getOnlineMediaScraper(
					context, scraperId);

			String page = HttpDownload.getInstance().downloadPage(movie.getDetailsUrl(),
					movie.getDetailsPageEncodeType());
			return scraper.extractDetails(page, movie.getId());
		}
	}

	public void analyzeMediaUrl(Context context, MediaSource sources,
			String format) {
		run(sources.getUrl(), new AnalyzeVideoThread(resultPool, sources, format));
	}

	private synchronized OnlineMediaScraper getOnlineMediaScraper(
			Context context, String scraperId) throws ScraperException {
		// TODO scraper params

		return new OnlineMediaScraper(scraperId, ScraperManager.getInstance()
				.getScraper(context, scraperId),
				new HashMap<String, String>(0));
	}

}
